<template>
  <!-- 只渲染 el-transfer -->
  <el-transfer
    v-bind="$attrs"
    v-model="selectedValue"
    :data="options"
    :props="transferProps"
    :titles="transferTitles"
    :filterable="transferFilterable"
    :button-texts="transferButtonTexts"
    @change="handleChange"
    :disabled="isLoading"
  >
    <!-- el-transfer 的 loading 状态通常不直接通过 prop 传递，而是通过外部包裹或内部数据加载状态来体现 -->
  </el-transfer>
</template>

<script setup>
import { ref, watch, computed, nextTick } from 'vue';
import { useDictStore } from '@/store';
// 显式导入 ElTransfer
import { ElTransfer } from 'element-plus';

const props = defineProps({
  code: {
    type: String,
    required: true,
  },
  perms: {
    type: Boolean,
    default: false,
  },
  modelValue: {
    // For v-model support, el-transfer 期望一个数组
    type: Array, // 明确为 Array 类型
    default: () => [], // 默认值为空数组
  },
  // el-transfer 特有 props
  transferTitles: {
    type: Array,
    default: () => ['源列表', '目标列表'], // 默认标题
  },
  transferFilterable: {
    type: Boolean,
    default: false, // 默认不可搜索
  },
  transferButtonTexts: {
    type: Array,
    default: () => [], // 默认按钮文本为空
  },
  // el-transfer 的数据映射，我们已经将字典数据映射为 { label, value }，所以可以直接使用
  transferProps: {
    type: Object,
    default: () => ({
      key: 'value', // 对应 options 里的 value
      label: 'label', // 对应 options 里的 label
    }),
  },
});

const emit = defineEmits(['update:modelValue', 'change']);

const dictStore = useDictStore();
const options = ref([]);
const isLoading = ref(false);
const dataLoaded = ref(false);

// 计算属性：始终返回 modelValue，并确保是数组类型
const selectedValue = computed({
  get() {
    // 确保 modelValue 始终是数组，以符合 el-transfer 的 v-model 期望
    return Array.isArray(props.modelValue) ? props.modelValue : [];
  },
  set(value) {
    emit('update:modelValue', value);
  },
});

const fetchDictionaryData = async () => {
  if (!props.code) return;

  isLoading.value = true;
  dataLoaded.value = false;

  try {
    const data = await dictStore.getDictionary(props.code, props.perms);
    options.value = data.map((item) => {
      const rawItemValue = item.value !== undefined ? item.value : item.id;
      let finalItemValue = rawItemValue;

      // 针对 el-transfer，其 key 通常是字符串或数字。
      // 这里的类型转换逻辑可以简化，因为 el-transfer 内部会处理 key 的匹配。
      // 但为了确保数据一致性，可以根据 modelValue 的元素类型进行转换。
      if (Array.isArray(props.modelValue) && props.modelValue.length > 0) {
        const targetValueType = typeof props.modelValue[0];
        if (
          targetValueType === 'number' &&
          typeof rawItemValue === 'string' &&
          !isNaN(Number(rawItemValue))
        ) {
          finalItemValue = Number(rawItemValue);
        } else if (
          targetValueType === 'string' &&
          typeof rawItemValue === 'number'
        ) {
          finalItemValue = String(rawItemValue);
        }
      } else if (
        typeof props.modelValue === 'number' &&
        typeof rawItemValue === 'string' &&
        !isNaN(Number(rawItemValue))
      ) {
        // 如果 modelValue 初始是单个数字，虽然 el-transfer 期望数组，但为了兼容性
        finalItemValue = Number(rawItemValue);
      } else if (
        typeof props.modelValue === 'string' &&
        typeof rawItemValue === 'number'
      ) {
        // 如果 modelValue 初始是单个字符串
        finalItemValue = String(rawItemValue);
      }

      return {
        label: item.label || item.name,
        value: finalItemValue, // 这个 value 会作为 el-transfer 的 key
      };
    });

    // 数据加载完成
    dataLoaded.value = true;

    // 确保在下一个tick中更新选中值，让组件能够正确回显
    await nextTick();
  } catch (error) {
    console.error('Failed to fetch dictionary data:', error);
    options.value = [];
    dataLoaded.value = true; // 即使出错也标记为已加载
  } finally {
    isLoading.value = false;
  }
};

// 监听 code 和 perms 变化，重新获取数据
watch([() => props.code, () => props.perms], fetchDictionaryData, {
  immediate: true,
});

const handleChange = (value) => {
  emit('update:modelValue', value);
  emit('change', value);
};

// 暴露一些有用的方法和属性
defineExpose({
  options,
  isLoading,
  dataLoaded,
  refresh: fetchDictionaryData,
});
</script>

<style scoped>
/* Add any specific styles for RaDictSelect here if needed */
</style>
